package tool;

import java.util.List;
import java.util.Arrays;
import java.util.HashMap;
import java.util.ArrayList;
import java.lang.reflect.Field;
import java.util.function.BiFunction;

/**
 * 获取和设置属性类
 */
public class GetAndSetField {
    /**
     * 获取属性方法
     * @param object    对象引用
     * @return  属性HashMap
     * @throws IllegalAccessException
     */
    public static HashMap<String, Object> getFieldValue(Object object) throws IllegalAccessException {
        //如果为null则返回null
        if(object == null){
            return null;
        }
        HashMap<String, Object> fieldValue = new HashMap<>();       //属性HashMap
        //获取属性列表
        Field[] fields = object.getClass().getDeclaredFields();
        //添加属性至属性HashMap
        for(Field field : fields){
            //取消访问检查
            field.setAccessible(true);
            //获取属性
            fieldValue.put(field.getName(), field.get(object));
            //设置访问检查
            field.setAccessible(false);
        }
        //返回数据
        return fieldValue;
    }

    /**
     * 获取属性方法
     * @param object    对象引用
     * @param getFields 获取属性名
     * @return  属性HashMap
     * @throws IllegalAccessException
     */
    public static HashMap<String, Object> getFieldValue(Object object, String[] getFields) throws IllegalAccessException {
        //如果为null则返回null
        if(object == null || getFields == null){
            return null;
        }
        List<String> asList = Arrays.asList(getFields);             //字段List
        HashMap<String, Object> fieldValue = new HashMap<>();       //属性HashMap
        //获取属性列表
        Field[] fields = object.getClass().getDeclaredFields();
        //添加指定属性至属性HashMap
        for(Field field : fields){
            String fieldName = field.getName();
            //如果属性被指定则添加至属性HashMap
            if(asList.contains(fieldName)){
                //取消访问检查
                field.setAccessible(true);
                //获取属性
                fieldValue.put(fieldName, field.get(object));
                //设置访问检查
                field.setAccessible(false);
            }
        }
        //返回数据
        return fieldValue;
    }

    /**
     * 设置属性方法
     * @param object    对象引用
     * @param setFields 设置属性
     * @return  设置成功属性
     * @throws IllegalAccessException
     */
    public static ArrayList<String> setFieldValue(Object object, HashMap<String, Object> setFields) throws IllegalAccessException {
        //如果为null则返回null
        if(object == null || setFields == null){
            return null;
        }
        Class<?> classes = object.getClass();                       //对象类
        ArrayList<String> setSuccessFields = new ArrayList<>();     //设置成功属性
        //设置指定属性
        for(String setField : setFields.keySet()){
            try{
                //获取属性
                Field field = classes.getDeclaredField(setField);
                //取消访问检查
                field.setAccessible(true);
                //设置属性
                field.set(object, setFields.get(setField));
                //设置访问检查
                field.setAccessible(false);
                //添加至设置成功属性
                setSuccessFields.add(setField);
            } catch (NoSuchFieldException err){}
        }
        //返回数据
        return setSuccessFields;
    }

    /**
     * 设置属性方法
     * @param object    对象引用
     * @param setFields 设置属性
     * @param biFunction  检查函数(属性名,属性值)
     * @return  设置成功属性
     */
    public static ArrayList<String> setFieldValue(Object object, HashMap<String, Object> setFields, BiFunction<String, Object, Boolean> biFunction) throws IllegalAccessException {
        //如果为null则返回null
        if(object == null || setFields == null || biFunction == null){
            return null;
        }
        Class<?> classes = object.getClass();                       //对象类
        ArrayList<String> setSuccessFields = new ArrayList<>();     //设置成功属性
        //设置指定属性
        for(String setField : setFields.keySet()){
            Object fieldValue = setFields.get(setField);
            //如果检查不通过则跳过
            if(!biFunction.apply(setField, fieldValue)){
                continue;
            }
            try{
                //获取属性
                Field field = classes.getDeclaredField(setField);
                //取消访问检查
                field.setAccessible(true);
                //设置属性
                field.set(object, fieldValue);
                //设置访问检查
                field.setAccessible(false);
                //添加至设置成功属性
                setSuccessFields.add(setField);
            } catch (NoSuchFieldException err){}
        }
        //返回数据
        return setSuccessFields;
    }
}